var SystemBanner = mongoose.model('system_BannerDefinitions');
var toolUtil = require('../common/utils/toolUtil');
var async = require('async');
var SystemMessage = mongoose.model('system_messages');
var system_userFeedbacks = mongoose.model('system_userFeedbacks');
var appStartInfo = mongoose.model('system_appStartInfo');
var deviceInfo = mongoose.model('system_deviceInfo');
var codeShortMessage = mongoose.model('system_codeShortMessage');
var systemChatMessageEntity = mongoose.model('system_chatMessages');//环信，TODO
var Question = mongoose.model('question');
var Community = mongoose.model('community');
var Users = mongoose.model('user');
var userAuthentication = mongoose.model('user_authentications');
var cacheUtil = require('../common/utils/cacheUtil');
var specialTopics = mongoose.model('system_specialTopics');
var freshNews = mongoose.model('system_freshNews');
var moment = require('moment');
var QuestionReport = mongoose.model('question_reports');
var communitySupplement = mongoose.model('community_supplements');
var operateMessage = mongoose.model('system_operateMessages')
var systemChatMessagesEntity = mongoose.model('system_chatMessages');
var neighbourActivity = mongoose.model('activity_neighbour');
var fs = require("fs");
var md5 = require('MD5');
var promotionCode = mongoose.model('system_promotionCode');
var offlineMessage = mongoose.model('system_offlineChatMessage');
var userDevice = mongoose.model('user_device_profile');
var appErrorLog = mongoose.model('app_error_log');
var replyAt = mongoose.model('question_replyAt');
var replyAtService = mongoose.model('question_replyAtService');
var ugcIndex = mongoose.model('system_ugcIndex');
var mysqlUtil = require('../common/utils/mysqlUtil');
/**
 * Created by wry on 2014/12/15.
 */


/**
 * 根据经纬度查询天气预报
 * @param lat
 * @param lon
 * @param callback
 */
exports.getWeatherService = function (lat, lon, callback) {
    restClient.get('http://api.map.baidu.com/telematics/v3/weather?location=' + lon + ',' + lat + '&output=json&ak=AvRqTglpaKICTZ5iwyn06KZj', function (data, response) {
        if (response.statusCode == 200) {
            try {
                var data1 = JSON.parse(data);
                if (data1.error == 0) {
                    var data = data1.results[0];
                    var result = {};
                    result['currentCity'] = data['currentCity'];
                    result['weather_data'] = data['weather_data'];
                    callback(null, result);
                } else {
                    var msg = {
                        "message": 'No result available'
                    }
                    callback(msg, null);
                }
            } catch (e) {
                callback(e, null);
            }
        } else {
            var err = {
                "message": 'statusCode:' + response.statusCode
            };
            callback(err, null);
        }
    }).on('error', function (err) {
        logger.error('get weather went wrong on the request' + err.message);
    });
};


/**
 * systemService.js
 *创建banner
 * @param userId:用户Id
 *author：chenjinzhuan
 * */
exports.createBannerService = function (userId, input, callback) {
    var tempBanner = new SystemBanner();
    tempBanner.stickyPage = input.stickyPage;
    tempBanner.banner = input.banner;
    tempBanner.isValid = true;
    tempBanner.lastModifiedBy = userId;
    tempBanner.dateLastModified = new Date();
    tempBanner.createdBy = userId;
    tempBanner.dateCreated = new Date();
    tempBanner.save(callback);
};

/**
 * systemService.js
 *上传banner图片
 *author：chenjinzhuan
 * */
exports.setImagesToBannerService = function (id, images, callback) {

    SystemBanner.findOne({_id: id}, function (err, systemBanner) {
        if (err) {
            console.log(err);
        } else {
            for (var i = 0; i < images.length && i < systemBanner.banner.length; i++) {
                systemBanner.banner[i].backgroundImageURL = images[i].backgroundImageURL;
            }
            systemBanner.save(callback);
        }
    });

};

/**
 * systemService.js
 *修改banner
 *author：chenjinzhuan
 * */
exports.updateBannerService = function (id, input, callback) {
    async.series([
            //更新banner
            function (callbackInner) {
                SystemBanner.update({_id: id}, input, callbackInner);
            },
            //更新最后修改日期
            function (callbackInner) {
                SystemBanner.update({_id: id}, {dateLastModified: new Date()}, callbackInner);
            }
        ],
        callback);
};

/**
 * systemService.js
 *删除banner
 *author：chenjinzhuan
 * */
exports.deleteBannerService = function (id, callback) {
    SystemBanner.remove({_id: id}, callback);
};

/**
 * systemService.js
 *获取指定的banner
 *author：chenjinzhuan
 * */
exports.getBannerService = function (token, stickyPage, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(null, null)
        } else {
            SystemBanner.findOne({
                stickyPage: stickyPage,
                isValid: true,
                community: user.community._id
            }, function (err, banner) {
                if (err) {
                    logger.error('Exception happened in getBannerService...!');
                    return callback(err, null);
                } else if (banner == null) {
                    logger.error('banner does not exist...!');
                    return callback(null, null);
                } else {
                    return callback(null, banner);
                }
            });
        }
    });
};

/**
 * 获取我的消息列表
 */
exports.getMyMessageListService = function (page, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            async.series([
                function (callbackInner) {
                    var index = Number(page) * listPageSize;
                    var data = [];
                    SystemMessage.find({'toUser': toolUtil.getUserObjIdByToken(token)}, 'fromUser category content _id dateCreated readFlag').skip(index).limit(listPageSize).populate('fromUser', '_id nickName images userType authenticationStatus')
                        .sort('-dateCreated')
                        .exec(function (err, result) {
                            if (result != null) {
                                async.eachSeries(result, function (temp, c1) {

                                    if (temp.fromUser == null) {
                                        temp._doc.fromUser = {
                                            nickName: temp.content.title,
                                            images: [{imageURL: wechatImage}]
                                        }
                                    }

                                    if (temp.content.questionDesc != null) {
                                        temp.content.questionDesc = temp.content.questionDesc.replace(/\@\{[0-9]\}/g, '')
                                    }

                                    if (temp.content.replyDesc != null && temp.content.replyId != null && temp.content.replyDesc.indexOf(atFlag) != -1) {
                                        replyAt.findOne({replyId: temp.content.replyId + ''}, function (err, at) {
                                            if (at != null && at.uList != null) {
                                                at.uList.forEach(function (user, i) {
                                                    temp.content.replyDesc = temp.content.replyDesc.replace(new RegExp("@\\{" + i + "\\}"), '@' + user.nickName + ' ')
                                                });
                                            }
                                            data.push(temp);
                                            c1()
                                        }).populate('uList', ' nickName');
                                    } else {
                                        data.push(temp);
                                        c1();
                                    }_id
                                }, function (err) {
                                    callbackInner(err, data);
                                })
                            } else {
                                callbackInner(err, data);
                            }
                        });
                },
                function (callbackInner) {
                    SystemMessage.count({
                        'toUser': toolUtil.getUserObjIdByToken(token),
                        readFlag: false
                    }, callbackInner);
                }
            ], callback)
        }
    });
};

/**
 * 获取运营推送消息列表
 * @param page
 * @param token
 * @param callback
 */
exports.getOperateMessageService = function (page, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            async.series([
                function (callbackInner) {
                    var index = Number(page) * listPageSize;
                    operateMessage.find({user: user._id}, 'tag openType message url messageId createdBy readFlag dateCreated').skip(index).limit(listPageSize).sort('-dateCreated')
                        .exec(callbackInner)
                },
                function (callbackInner) {
                    operateMessage.count({user: user._id, readFlag: false}, callbackInner);
                }
            ], callback)
        }
    })
};

/**
 * 清空消息列表
 * @param token
 * @param callback
 */
exports.emptyMyMessageService = function (token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            SystemMessage.remove({toUser: user._id}, callback)
        }
    });
};

/**
 * 清空未读回复消息
 * @param token
 * @param callback
 */
exports.emptyUnReadMessageService = function (token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            SystemMessage.find({toUser: user._id, readFlag: false}, function (err, results) {
                async.each(results, function (message, callbackInner) {
                    SystemMessage.update({_id: message._id}, {readFlag: true}).exec(callbackInner)
                }, function (err) {
                    callback(err, null)
                })
            })
        }
    })
};

/**
 * 清空运营推送消息
 */
exports.emptyOperateMessageService = function (token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            operateMessage.remove({user: user._id}, callback)
        }
    })
};

/**
 * 清空未读运营发布消息
 * @param token
 * @param callback
 */
exports.emptyUnReadOperateMessageService = function (token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            operateMessage.find({user: user._id, readFlag: false}, function (err, results) {
                async.each(results, function (message, callbackInner) {
                    operateMessage.update({_id: message._id}, {readFlag: true}).exec(callbackInner)
                }, function (err) {
                    callback(err, null)
                })
            })
        }
    })
}

/**
 * 设置回复消息为已读状态
 */
exports.setMessageAsReadService = function (token, messageId, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            SystemMessage.find({toUser: user._id, 'content.contentId': messageId}, function (err, results) {
                async.each(results, function (message, callbackInner) {
                    SystemMessage.update({_id: message._id}, {readFlag: true}).exec(callbackInner)
                }, function (err) {
                    callback(err, null)
                })
            })
        }
    });
};

/**
 * 设置运营推送消息已读
 * @param token
 * @param operateId
 * @param callback
 */
exports.setOperateMessageAsReadService = function (token, clickSource, messageId, callback) {
    var opt = {
        readFlag: true,
        clickSource: clickSource
    };

    logger.info(opt);
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            operateMessage.find({messageId: messageId, user: user._id}, function (err, results) {
                async.each(results, function (message, callbackInner) {
                    if (message.clickSource != null) {
                        callbackInner()
                    } else {
                        operateMessage.update({_id: message._id}, opt).exec(callbackInner)
                    }
                }, function (err) {
                    callback(err, null)
                });
            });
        }
    });
};

exports.deleteReplyMessageService = function (id, callback) {
    SystemMessage.remove({_id: id}, callback);
};

exports.deleteOperateMessageService = function (id, callback) {
    operateMessage.remove({_id: id}, callback);
};

/**
 * 用户反馈
 */
exports.postFeedbackService = function (token, input, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            var temp = new system_userFeedbacks();
            temp.createdBy = user._id;
            temp.desc = input.desc;
            temp.community = user.community._id;
            temp.save(callback);

            var message = '你的版本OUT啦，快去应用商店搜索“宝宝树66小区”下载新版APP吧，新功能更6哦！';
            toolUtil.pushCustomerServiceMessage(user, message);
        }
    });
};

exports.getFeedbackListService = function (communityId, callback) {
    if (communityId == '1') {
        system_userFeedbacks.find({}, 'dateCreated createdBy desc community').populate('createdBy', 'nickName').populate('community', 'communityName')
            .sort('-dateCreated').exec(callback);
    } else {
        system_userFeedbacks.find({community: communityId}, 'dateCreated createdBy desc community').populate('createdBy', 'nickName').populate('community', 'communityName')
            .sort('-dateCreated').exec(callback);
    }
};

exports.postAppStartInfoService = function (input, callback) {
    var temp = new appStartInfo();
    temp.deviceId = input.deviceId;
    temp.net_provider = input.net_provider;
    temp.net_type = input.net_type;
    temp.gps_x = input.gps_x;
    temp.gps_y = input.gps_y;
    temp.userId = input.userId;
    if (temp.community != null && temp.community != '')
        temp.community = input.community;
    temp.gps_name = input.gps_name;
    temp.save(callback);
};

exports.postDeviceInfoService = function (input, callback) {
    var temp = new deviceInfo();
    temp.deviceId = input.deviceId;
    temp.mobile_model = input.mobile_model;
    temp.osv = input.osv;
    temp.width = input.width;
    temp.height = input.height;
    temp.channelId = input.channelId;
    temp.userId = input.userId;
    temp.sim_no = input.sim_no;
    temp.mac = input.mac;
    temp.save(callback);
};

exports.searchTermsService = function (token, keyword, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            var temp = encodeURIComponent(keyword);
            restClient.get('http://' + SolrHost + '/core0/terms?wt=json&indent=true&terms.fl=desc&terms.prefix=' + temp, function (data, response) {
                logger.info(data);
                if (typeof data == 'string') {
                    try {
                        data = JSON.parse(data);
                    } catch (e) {

                    }
                }
                if (typeof data == "object" && data.terms != null) {
                    var results = new Array();
                    var terms = data.terms.desc;
                    terms.forEach(function (term) {
                        if (typeof term == 'string') {
                            results.push(term);
                        }
                    });
                    callback(null, results);
                } else {
                    logger.error(data);
                    callback(null, null);
                }
            }).on('error', function (err) {
                logger.error('search went wrong on the request' + err.message);
            });
        }
    })
};

exports.searchQuestionAndReplyService = function (keyword, token, callback) {

    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {

            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……&*（）&mdash;—|{}【】‘；：”“'。，、？]");
            var rs = "";
            for (var i = 0; i < keyword.length; i++) {
                rs = rs + keyword.substr(i, 1).replace(pattern, '');
            }

            var temp = encodeURIComponent(rs);

            if (temp == null || temp == '') {
                var res = new Array();
                callback(null, res);
            } else {
                async.waterfall([
                    function (callbackInner) {

                        var questions = [];

                        restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7Ddesc%3A' + temp + '&fq=community%3A' + user.community._id + '&fl=_id&wt=json&indent=true&hl=true&hl.fl=desc&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>', function (data, response) {

                            if (typeof data == 'string') {
                                try {
                                    data = JSON.parse(data);
                                } catch (e) {

                                }
                            }
                            if (typeof data == "object" && data.response != null) {

                                var docs = data.response.docs;
                                var ids = new Array(docs.length);
                                console.log(docs.length);
                                for (var i = 0; i < docs.length; i++) {
                                    ids[i] = docs[i]._id;
                                }

                                async.eachSeries(ids, function (id, callbackInner1) {
                                    Question.findOne({
                                        _id: id,
                                        community: user.community._id,
                                        isValid: true
                                    }, '_id desc createdBy')
                                        .populate('createdBy', '_id nickName').exec(function (err, result) {
                                            if (result != null) {
                                                questions.push(result);
                                            }
                                            callbackInner1();
                                        });
                                }, function (err) {
                                    questions.forEach(function (question) {
                                        question._doc.desc = data.highlighting[question._id].desc[0];
                                        if (question._doc.tag == null || question._doc.tag.length == 0) {
                                            question._doc.tag = undefined;
                                        }
                                    });
                                    callbackInner(err, questions);
                                })

                            } else {
                                logger.error(data);
                                callbackInner(null, questions);
                            }
                        }).on('error', function (err) {
                            callbackInner(null, questions);
                        });
                    },
                    function (questions, callbackInner) {

                        var questionList = [];

                        restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7Dreplies%3A' + temp + '&fq=community%3A' + user.community._id + '&fl=_id&wt=json&indent=true&hl=true&hl.fl=*replyDesc&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
                            if (typeof data == 'string') {
                                try {
                                    data = JSON.parse(data);
                                } catch (e) {

                                }
                            }
                            if (typeof data == "object" && data.response != null) {
                                var docs = data.response.docs;
                                var ids = new Array(docs.length);
                                console.log(docs.length);
                                for (var i = 0; i < docs.length; i++) {
                                    ids[i] = docs[i]._id;
                                }

                                async.eachSeries(ids, function (id, callbackInner1) {
                                    Question.findOne({
                                        _id: id,
                                        community: user.community._id,
                                        isValid: true
                                    }, '_id desc createdBy')
                                        .populate('createdBy', '_id nickName').exec(function (err, result) {
                                            if (result != null) {
                                                questionList.push(result);
                                            }
                                            callbackInner1()
                                        })
                                }, function (err) {
                                    questionList.forEach(function (question) {
                                        var hl = data.highlighting[question._id];

                                        for (var k in hl) {
                                            question._doc['reply'] = hl[k][0];
                                            break;
                                        }
                                        var v = true;
                                        for (var i = 0; i < questions.length; i++) {
                                            var v = question._id + '';
                                            if (v == questions[i]._id) {
                                                v = false;
                                                questions[i]._doc['reply'] = question._doc.reply;
                                                break;
                                            }
                                        }
                                        if (v) {
                                            questions.push(question)
                                        }
                                    });
                                    if (questions != null && questions.length > 0) {
                                        try {
                                            keyword = keyword.trim();
                                            redisClient.zincrby(user.community._id, -1, keyword);
                                        } catch (e) {
                                            logger.error(e);
                                        }
                                    }
                                    callbackInner(null, questions);
                                });

                            } else {
                                callbackInner(null, questions);
                            }
                        }).on('error', function (err) {
                            callbackInner(err, null);
                        });
                    }
                ], callback);
            }
        }
    });
};

/**
 * 搜索专题
 * @param keyword
 * @param token
 * @param callback
 */
exports.searchTopicService = function (keyword, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……&*（）&mdash;—|{}【】‘；：”“'。，、？]");
            var rs = "";
            for (var i = 0; i < keyword.length; i++) {
                rs = rs + keyword.substr(i, 1).replace(pattern, '');
            }

            var temp = encodeURIComponent(rs);

            if (temp == null || temp == '') {
                var res = new Array();
                callback(null, res);
            } else {

                restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7Dtitle%3A' + temp + '+OR+desc%3A' + temp + '&fl=_id&wt=json&indent=true&hl=true&hl.fl=title+desc&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
                    if (typeof data == 'string') {
                        try {
                            data = JSON.parse(data);
                        } catch (e) {

                        }
                    }
                    if (typeof data == "object" && data.response != null) {
                        var docs = data.response.docs;
                        var ids = new Array(docs.length);
                        console.log(docs.length);
                        for (var i = 0; i < docs.length; i++) {
                            ids[i] = docs[i]._id;
                        }

                        specialTopics.find({
                            _id: {'$in': ids},
                            community: user.community._id
                        }, '_id title', function (err, results) {
                            if (results == undefined || results == null) {
                                callback(null, null);
                            } else {
                                results.forEach(function (topic) {
                                    if (data.highlighting[topic._id].title != null)
                                        topic._doc.title = data.highlighting[topic._id].title[0];
                                    if (data.highlighting[topic._id].desc != null) {
                                        var desc = data.highlighting[topic._id].desc[0];
                                        topic._doc['desc'] = desc.replace(/\n/g, '');
                                    }
                                });
                                callback(null, results);
                            }
                        })

                    } else {
                        callback(null, null);
                    }
                }).on('error', function (err) {
                    callback(err, null);
                });

            }
        }
    });
};
//&fq=authenticationStatus%3Atrue
exports.globalSearchService = function (keyword, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {


            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……（）;—|{}【】‘；：”“'。，、？]");
            var rs = "";
            for (var i = 0; i < keyword.length; i++) {
                rs = rs + keyword.substr(i, 1).replace(pattern, '');
            }

            var temp = encodeURIComponent(rs);

            async.series([
                function (callbackInner) {
                    var users = [];
                    restClient.get('http://' + SolrHost + '/core0/select?q=user%3A' + temp + '&fq=community%3A' + user.community._id + '&fq=authenticationStatus%3Atrue&rows=3&wt=json&indent=true&hl=true&hl.fl=nickName+roomUnit+roomNumber&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
                        if (response.statusCode == 200) {
                            data = JSON.parse(data);
                            var docs = data.response.docs;
                            var hl = data.highlighting;

                            var ids = new Array(docs.length);

                            for (var i = 0; i < docs.length; i++) {
                                ids[i] = docs[i]._id;
                            }

                            async.eachSeries(ids, function (id, callback1) {
                                Users.findOne({_id: id}, 'nickName images roomUnit userPortrait gender userType authenticationStatus').populate('userPortrait', 'value')
                                    .exec(function (err, result) {
                                        if (result != null) {
                                            if (hl[id].nickName != null)
                                                result.nickName = hl[id].nickName[0];
                                            if (hl[id].roomUnit != null)
                                                result.roomUnit = hl[id].roomUnit[0];
                                            users.push(result);
                                        }
                                        callback1();
                                    })
                            }, function (err) {
                                var c1 = {
                                    users: users,
                                    userNum: data.response.numFound
                                };
                                callbackInner(err, c1);
                            })
                        } else {
                            var c1 = {
                                users: users,
                                userNum: 0
                            }
                            callbackInner(err, c1);
                        }
                    }).on('error', function (err) {
                        var c1 = {
                            users: users,
                            userNum: 0
                        }
                        callbackInner(err, c1);
                    });

                },
                function (callbackInner) {
                    var questions = [];
                    restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7DdescReplies%3A' + temp + '&fq=community%3A' + user.community._id + '&fq=isValid%3Atrue&rows=3&wt=json&indent=true&hl=true&&hl.fl=title+desc+replies&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
                        if (response.statusCode == 200) {
                            data = JSON.parse(data);
                            var docs = data.response.docs;
                            var hl = data.highlighting;

                            async.eachSeries(docs, function (doc, callback1) {
                                if (doc.category == 'neighbourActivity') {
                                    neighbourActivity.findOne({_id: doc._id}, '_id desc title createdBy category', function (err, result) {
                                        if (result != null) {
                                            if (hl[doc._id].title != null)
                                                result.title = hl[doc._id].title[0];
                                            if (hl[doc._id].desc != null)
                                                result.desc = hl[doc._id].desc[0];
                                            if (hl[doc._id].replies != null) {
                                                result._doc['reply'] = hl[doc._id].replies[0];
                                                result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
                                            }
                                            questions.push(result);
                                        }
                                        callback1();
                                    })
                                } else {
                                    Question.findOne({_id: doc._id}, '_id desc createdBy category', function (err, result) {
                                        if (result != null) {
                                            if (hl[doc._id].desc != null)
                                                result.desc = hl[doc._id].desc[0];
                                            if (hl[doc._id].replies != null) {
                                                result._doc['reply'] = hl[doc._id].replies[0];
                                                result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
                                            }
                                            questions.push(result);
                                        }
                                        callback1();
                                    });
                                }
                            }, function (err) {
                                var c1 = {
                                    questions: questions,
                                    questionNum: data.response.numFound
                                };
                                callbackInner(err, c1);
                            })
                        } else {
                            var c1 = {
                                questions: questions,
                                questionNum: data.response.numFound
                            };
                            callbackInner(null, c1);
                        }
                    }).on('error', function (err) {
                        var c1 = {
                            questions: questions,
                            questionNum: data.response.numFound
                        };
                        callbackInner(err, c1);
                    });
                }
            ], callback)
        }
    })
};

/**
 * 全局搜索1.6.0
 * @param keyword
 * @param page
 * @param token
 * @param callback
 */
//exports.searchAppUgcService = function (keyword, page, token, callback) {
//
//    logger.debug('838');
//
//    toolUtil.getUserByToken(token, function (err, user) {
//        if (err) {
//            callback(err, null)
//        } else {
//
//            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……（）;—|{}【】‘；：”“'。，、？]");
//            var rs = "";
//            for (var i = 0; i < keyword.length; i++) {
//                rs = rs + keyword.substr(i, 1).replace(pattern, '');
//            }
//
//            var temp = encodeURIComponent(rs);
//
//            var index = Number(page) * listPageSize;
//
//            var questions = [];
//
//            restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7DdescTitle%3A' + temp + '&fq=community%3A' + user.community._id + '&fq=isValid%3Atrue&start=' + index + '&rows=' + listPageSize + '&wt=json&indent=true&hl=true&&hl.fl=title+desc+replies&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
//                if (response.statusCode == 200) {
//                    data = JSON.parse(data);
//                    var docs = data.response.docs;
//                    var hl = data.highlighting;
//
//                    async.eachSeries(docs, function (doc, callback1) {
//
//                        if (doc.category == 'neighbourActivity') {
//                            neighbourActivity.findOne({_id: doc._id}, '_id desc title createdBy activityType category dateCreated replies images partakeNum', function (err, result) {
//                                if (result != null) {
//                                    if (hl[doc._id].title != null)
//                                        result.title = hl[doc._id].title[0];
//                                    if (hl[doc._id].desc != null)
//                                        result.desc = hl[doc._id].desc[0];
//                                    if (hl[doc._id].replies != null) {
//                                        result._doc['reply'] = hl[doc._id].replies[0];
//                                        result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
//                                    }
//                                    result._doc.partakeNum = toolUtil.transformNumber(result.partakeNum);
//
//                                    result._doc['replyCountStr'] = toolUtil.transformNumber(result.replies.length);
//                                    if (result.images != null && result.images.length > 0) {
//                                        result._doc['imageURL'] = result.images[0].imageURL;
//                                    }
//                                    if (result.activityType == null) {
//                                        result._doc.activityType = 2
//                                    }
//                                    result.replies = undefined;
//                                    result.images = undefined;
//
//                                    questions.push(result);
//                                }
//                                callback1();
//                            }).populate('createdBy', 'nickName images userType authenticationStatus')
//                        } else {
//                            Question.findOne({_id: doc._id}, '_id desc createdBy category dateCreated replies images', function (err, result) {
//                                if (result != null) {
//                                    if (hl[doc._id].desc != null)
//                                        result.desc = hl[doc._id].desc[0];
//                                    if (hl[doc._id].replies != null) {
//                                        result._doc['reply'] = hl[doc._id].replies[0];
//                                        result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
//                                    }
//
//                                    result._doc['replyCountStr'] = toolUtil.transformNumber(result.replies.length);
//                                    if (result.images != null && result.images.length > 0) {
//                                        result._doc['imageURL'] = result.images[0].imageURL;
//                                    }
//                                    result.replies = undefined;
//                                    result.images = undefined;
//                                    questions.push(result);
//                                }
//                                callback1();
//                            }).populate('createdBy', 'nickName images userType authenticationStatus');
//                        }
//                    }, function (err) {
//                        callback(err, questions);
//                    })
//                } else {
//                    callback(null, questions);
//                }
//            }).on('error', function (err) {
//                callback(err, questions);
//            });
//        }
//    })
//}

exports.searchUserService = function (keyword, page, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……（）;—|{}【】‘；：”“'。，、？]");
            var rs = "";
            for (var i = 0; i < keyword.length; i++) {
                rs = rs + keyword.substr(i, 1).replace(pattern, '');
            }

            var temp = encodeURIComponent(rs);

            var index = Number(page) * listPageSize;

            var users = [];
            restClient.get('http://' + SolrHost + '/core0/select?q=user%3A' + temp + '&fq=community%3A' + user.community._id + '&fq=authenticationStatus%3Atrue&start=' + index + '&rows=' + listPageSize + '&wt=json&indent=true&hl=true&hl.fl=nickName+roomUnit+roomNumber&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
                if (response.statusCode == 200) {
                    data = JSON.parse(data);
                    var docs = data.response.docs;
                    var hl = data.highlighting;

                    var ids = new Array(docs.length);

                    for (var i = 0; i < docs.length; i++) {
                        ids[i] = docs[i]._id;
                    }

                    async.eachSeries(ids, function (id, callback1) {
                        Users.findOne({_id: id}, 'nickName images roomUnit userPortrait gender userType authenticationStatus').populate('userPortrait', 'value')
                            .exec(function (err, result) {
                                if (result != null) {
                                    result._doc['originalName'] = result.nickName;
                                    if (hl[id].nickName != null)
                                        result.nickName = hl[id].nickName[0];
                                    if (hl[id].roomUnit != null)
                                        result.roomUnit = hl[id].roomUnit[0];
                                    users.push(result);
                                }
                                callback1();
                            })
                    }, function (err) {
                        callback(err, users);
                    })
                } else {
                    callback(err, users);
                }
            }).on('error', function (err) {
                callback(err, users);
            });
        }
    })
};

/**
 * 全局搜索1.6.0
 * @param keyword
 * @param page
 * @param token
 * @param callback
 */
exports.searchAppUgcService = function (keyword, page, token, callback) {

    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {

            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……（）;—|{}【】‘；：”“'。，、？]");
            var rs = "";
            for (var i = 0; i < keyword.length; i++) {
                rs = rs + keyword.substr(i, 1).replace(pattern, '');
            }

            var temp = encodeURIComponent(rs);

            var index = Number(page) * listPageSize;

            var questions = [];

            restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7DdescTitle%3A' + temp + '&fq=community%3A' + user.community._id + '&fq=isValid%3Atrue&start=' + index + '&rows=' + listPageSize + '&wt=json&indent=true&hl=true&&hl.fl=title+desc+replies&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {

                if (response.statusCode == 200) {
                    data = JSON.parse(data);
                    var docs = data.response.docs;
                    var hl = data.highlighting;
                    logger.debug('docs:');
                    logger.debug(docs);

                    var questionOpt = {};
                    questionOpt.community = user.community._id;
                    Community.findOne({_id:questionOpt.community},'communityType').exec(function(err,result)
                    {
                        logger.debug(result);
                        if(result.communityType == 0){
                            delete  questionOpt.community;
                        }
                        async.eachSeries(docs, function (doc, callback1) {
                            questionOpt._id = doc._id;
                            Question.findOne(questionOpt, '_id desc createdBy level category dateCreated replies images praiseCount', function (err, result) {
                                if (result != null) {
                                    if (hl[doc._id].desc != null)
                                        result.desc = hl[doc._id].desc[0];
                                    if (hl[doc._id].replies != null) {
                                        result._doc['reply'] = hl[doc._id].replies[0];
                                        result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
                                    }
                                    result._doc['browserCountStr'] = toolUtil.transformNumber(result._doc.browserCount);
                                    result._doc['isPrime'] = result.level == 1;

                                    result._doc['replyCountStr'] = toolUtil.transformNumber(result.replies.length);
                                    if (result.images != null && result.images.length > 0) {
                                        result._doc['imageURL'] = result.images[0].imageURL;
                                    }
                                    result.replies = undefined;
                                    result.images = undefined;
                                    ugcIndex.findOne({ugcId: doc._id}, function (err, index) {
                                        result._doc['isTop'] = index.displayOrder ? true : false;
                                        questions.push(result);
                                        callback1();
                                    });
                                }
                            }).populate('createdBy', 'nickName images userType authenticationStatus').populate('tag', 'category value _id');



                        }, function (err) {
                            callback(err, questions);
                        })

                    });

                } else {
                    logger.debug('ugc failure');
                    callback(null, questions);
                }
            }).on('error', function (err) {
                logger.debug('ugc failure:' + err);
                callback(err, questions);
            });
        }
    })
}

/**
 * 版主帖子搜索
 * @param keyword
 * @param page
 * @param token
 * @param callback
 */
exports.searchAppQuestionService = function (keyword, page, token,flag,communityId, callback) {
    <!--  宝宝树66小区二次改造    add   gct  20170808   start   -->
   var communityId=communityId;
    <!--  宝宝树66小区二次改造    add   gct  20170808   end   -->
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            var searchArray = [];
            var index = Number(page) * listPageSize;
            var pattern = new RegExp(keyword);

            var questionOpt = {};
            <!--  宝宝树66小区二次改造    mod   gct  20170808   start   -->
            if("0"==flag)
            {
                questionOpt.community = user.community._id;
            }
            else {
                questionOpt.community =communityId;
            }
            <!--  宝宝树66小区二次改造    mod   gct  20170808   end   -->
            Community.findOne({_id:questionOpt.community},'communityType').exec(function(err,result) {
                if (result.communityType == 0) {
                    logger.debug('虚拟小区成员');
                    delete  questionOpt.community;
                }else {
                    logger.debug('非虚拟小区成员');
                }

                questionOpt.desc = pattern;
                logger.debug(JSON.stringify(questionOpt)+pattern);
                Question.find(questionOpt, '_id displayOrder desc createdBy level category dateCreated images praiseCount replies ')
                    .populate('createdBy', 'nickName images userType authenticationStatus')
                    .populate('tag', 'category value _id')
                    .sort('-dateCreated')
                    .skip(index).limit(listPageSize)
                    .exec(function (err, docs) {
                        if (docs != null) {

                            async.eachSeries(docs, function (results, callback1) {
                                try {
                                    results._doc["isTop"] = results.displayOrder ? true : false;
                                    results._doc.browserCountStr = results.browserCount || 0;
                                    results._doc.isPrime = results.level === 1;
                                    results._doc.replyCountStr = results.replies.length || 0;

                                    if (results.images != null && results.images.length > 0) {
                                        results._doc['imageURL'] = result.images[0].imageURL;
                                    }
                                    results._doc.replies = undefined;
                                    searchArray.push(results);
                                } catch (exception) {
                                    results._doc.isTop = false;
                                    results._doc.browserCountStr = 0 + '';
                                    results._doc.replyCountStr = 0 + '';
                                    results._doc.isPrime = false;
                                    searchArray.push(results);
                                }
                                callback1();
                            }, function (err) {
                                console.log('执行完毕---------------');
                                callback(err, searchArray);
                            });
                        }
                        else {
                            searchArray.push({desc: "不存在"});
                            callback(err, searchArray);
                        }
                    });
            });
        }
    });
}

exports.searchUgcService = function (keyword, page, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {

            var pattern = new RegExp("[`~!@#$^&*()=|{}':;',\\[\\].<>/?~！@#￥……（）;—|{}【】‘；：”“'。，、？]");
            var rs = "";
            for (var i = 0; i < keyword.length; i++) {
                rs = rs + keyword.substr(i, 1).replace(pattern, '');
            }

            var temp = encodeURIComponent(rs);

            var index = Number(page) * listPageSize;

            var questions = [];

            restClient.get('http://' + SolrHost + '/core0/select?q=%7B!edismax+mm%3D"1<50%25+4<-45%25"%7DdescReplies%3A' + temp + '&fq=community%3A' + user.community._id + '&fq=isValid%3Atrue&start=' + index + '&rows=' + listPageSize + '&wt=json&indent=true&hl=true&&hl.fl=title+desc+replies&hl.simple.pre=<font+color%3D%27%23' + hlColor + '%27>&hl.simple.post=<%2Ffont>&hl.fragsize=20', function (data, response) {
                if (response.statusCode == 200) {
                    data = JSON.parse(data);
                    var docs = data.response.docs;
                    var hl = data.highlighting;

                    async.eachSeries(docs, function (doc, callback1) {

                        if (doc.category == 'neighbourActivity') {
                            neighbourActivity.findOne({_id: doc._id}, '_id desc title createdBy category', function (err, result) {
                                if (result != null) {
                                    if (hl[doc._id].title != null)
                                        result.title = hl[doc._id].title[0];
                                    if (hl[doc._id].desc != null)
                                        result.desc = hl[doc._id].desc[0];
                                    if (hl[doc._id].replies != null) {
                                        result._doc['reply'] = hl[doc._id].replies[0];
                                        result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
                                    }
                                    questions.push(result);
                                }
                                callback1();
                            })
                        } else {
                            Question.findOne({_id: doc._id}, '_id desc createdBy category', function (err, result) {
                                if (result != null) {
                                    if (hl[doc._id].desc != null)
                                        result.desc = hl[doc._id].desc[0];
                                    if (hl[doc._id].replies != null) {
                                        result._doc['reply'] = hl[doc._id].replies[0];
                                        result._doc.reply = result._doc.reply.replace(/@\{\d+\}/g, '');
                                    }
                                    questions.push(result);
                                }
                                callback1();
                            });
                        }
                    }, function (err) {
                        callback(err, questions);
                    })
                } else {
                    callback(null, questions);
                }
            }).on('error', function (err) {
                callback(err, questions);
            });
        }
    })
};


exports.getMessageChatListService = function (token, vCode, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            async.series([
                function (callbackInner) {

                    if (vCode != null && Number(vCode) >= appVersionCode) {
                        toolUtil.getCustomerServiceByCommunityId(user.community._id, function (err, result) {
                            var data = {
                                "name": result.nickName,
                                "huanxinId": result.huanxinUserName,
                                "imageURL": result.images[0].imageURL,
                                "isGroup": false,
                                "serviceId": 'superservice',
                                "type": "service"
                            };
                            callbackInner(err, data);
                        });
                    } else {
                        Users.findOne({'huanxinUserName': '66customerservice'}, '_id images huanxinUserName nickName', function (err, result) {
                            var data = {
                                "name": result.nickName,
                                "huanxinId": result.huanxinUserName,
                                "imageURL": result.images[0].imageURL,
                                "isGroup": false,
                                "type": "service"
                            };
                            callbackInner(err, data);
                        });
                    }
                },
                function (callbackInner) {
                    Community.findOne({_id: user.community._id}, 'communityName chatGroupId communityLogo', function (err, result) {
                        toolUtil.getAndCacheHuanXinToken(function (err, token) {
                            var args = {
                                headers: {
                                    "Content-Type": "application/json",
                                    "Authorization": "Bearer " + token
                                }
                            };
                            var isJoin = false;
                            restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/users/" + user.huanxinUserName + "/joined_chatgroups", args, function (data, response) {
                                if (response.statusCode == '200' && data.data != null) {
                                    logger.debug(data.data);
                                    data.data.forEach(function (group) {
                                        if (result.chatGroupId == group.groupid) {
                                            isJoin = true;
                                        }
                                    })
                                }
                                logger.info(isJoin);
                                if (!isJoin) {
                                    var args = {
                                        data: {},
                                        headers: {
                                            "Content-Type": "application/json",
                                            "Authorization": "Bearer " + token
                                        }
                                    };
                                    restClient.post("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatgroups/" + result.chatGroupId + "/users/" + user.huanxinUserName, args, function (data, response) {
                                        if (response.statusCode == 200) {
                                            logger.info("Success to join community group");
                                        }

                                    }).on('error', function (err) {
                                        logger.error('join community' + err.message);
                                    });
                                }
                            }).on('error', function (err) {
                                logger.error('join community' + err.message);
                            });
                        });

                        var data = {
                            "name": result.communityName + '群聊大厅',
                            "huanxinId": result.chatGroupId,
                            "isGroup": true,
                            "imageURL": result.communityLogo,
                            "serviceId": result.chatGroupId,
                            "type": "group"
                        };
                        callbackInner(err, data);
                    });
                }
            ], callback);
        }
    });
};

// 取得环信聊天记录历史，1小时前
exports.getHxChatMessagesDownLoadUrl = function (ymdh, callback) {
    toolUtil.getAndCacheHuanXinToken(function (err, token) {
        logger.debug("hx token:" + token);
        var args = {
            headers: {
                "Content-Type": "application/json",
                "Authorization": "Bearer " + token
            }
        };
        restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages/" + ymdh, args, function (data, response) {

            logger.debug("getHxChatMessagesDownLoadUrl success...");
            logger.debug("data start:");
            logger.debug(data);
            logger.debug("data end:");
            callback(null, "SUCCESS");
        }).on('error', function (err) {
            logger.error('getHxChatMessagesDownLoadUrl' + err.message);
            callback(err, null);
        });
    });
};


/*环信导出聊天记录
 参考 pushCustomerServiceMessage()

 TODO:环信服务器端REST API常见错误码
 http://www.easemob.com/docs/helps/
 建议对APP自己的服务器端调用的环信REST API结果做容错处理。比如要catch接口调用返回的异常，对于timeout这样的错误应该做重试。
 对于系统级别错误或重试后仍旧出错，应该记录到系统日志，并及时报警提示运维人员做补救措施，如人工补发。

 Unix时间戳(Unix timestamp)转换工具 - 站长工具
 http://tool.chinaz.com/Tools/unixtime.aspx

 */
exports.exportChatMessageListService = function (users, message) {
    Users.findOne({'nickName': '小6客服'}, '_id images huanxinUserName', function (err, result) {
        toolUtil.getAndCacheHuanXinToken(function (err, token) {

            var args = {
                /*data: {
                 ...
                 },*/
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": "Bearer " + token
                    //"Authorization": "Bearer " + "YWMtxc6K0L1aEeKf9LWFzT9xEAAAAT7MNR_9OcNq-GwPsKwj_TruuxZfFSC2eIQ"
                }
            };


            //TODO：程序里timestamp需要13位长度，在线工具中仅需要10位长度.
            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages", args, function (data, response) {//间隔五秒左右自动从环信server发送一批聊天记录，client负责接收存储

            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?ql=select * where timestamp>"+1425916800, args, function (data, response) {//时间戳之后的
            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=100&ql=select+*+where+timestamp>1427817600333", args, function (data, response) {//分页.


            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=10&cursor=MTYxOTcyOTYyNDpnR2tBQVFNQWdHa0FCZ0ZHczBKN0F3Q0FkUUFRYUdpdkt2ZU1FZU9vNU4zVllyT2pqUUNBZFFBUWFHaXZJUGVNRWVPMjdMRWo5b0w4dEFB", args, function (data, response) {
            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=10&cursor=MTYxOTcyOTYyNDpnR2tBQVFNQWdHa0FCZ0ZHczFuSG93Q0FkUUFROW94S0lQZVBFZU9mTEQxQWVMdHEyQUNBZFFBUTlvd2pFUGVQRWVPaHFWa1l0ZjA2dEFB", args, function (data, response) {
            //restClient.get("https://a1.easemob.com/easemob-demo/chatdemoui/chatmessages?limit=10&cursor=MTYxOTcyOTYyNDpnR2tBQVFNQWdHa0FCZ0ZHczFuSG93Q0FkUUFROW94S0lQZVBFZU9mTEQxQWVMdHEyQUNBZFFBUTlvd2pFUGVQRWVPaHFWa1l0ZjA2dEFB", args, function (data, response) {

            //2015-04-11
            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=10&ql=select+*+where+timestamp>1425139200000&cursor=MTYxOTcyOTYyNDpnR2tBQVFNQWdHa0FCZ0ZHczBKN0F3Q0FkUUFRYUdpdkt2ZU1FZU9vNU4zVllyT2pqUUNBZFFBUWFHaXZJUGVNRWVPMjdMRWo5b0w4dEFB", args, function (data, response) {/*2015-3-1之后的记录*/

            //TODO;2015-4-11导出1000条记录，

            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=1000&ql=select+*+where+timestamp>1423858579000", args, function (data, response) {//下一页
            //restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=1000&cursor=", args, function (data, response) {//下一页
            restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=1000&cursor=LTU2ODc0MzQzOllKb01Dcjc1RWVTUU5kVjM2WUtkRHc", args, function (data, response) {//TODO：用这句话到下来的所有聊天记录，12643条记录，

                logger.debug("1>>>>>>exportChatMessageListService(),（环信导出聊天记录）");
                logger.debug(">>>>>>data:");

                logger.debug(">>>>>>data.cursor:");
                logger.debug(data.cursor);//count: 收到多少条，
                var cursor1 = data.cursor;//TODO:重命名

                logger.debug(">>>>>>data.count:");
                logger.debug(data.count);//count: 收到多少条，
                count1 = data.count;
                logger.debug(data);//count: 收到多少条，
                //TODO: cursor分页方式的response里的 duration=6字段：是【cursor持续6秒】的意思吗？
                data.entities.forEach(function (parm1) {
                    //logger.debug(">>>>>>parm1:");
                    //logger.debug(parm1);
                    //logger.debug(">>>>>>parm1.payload:");
                    //logger.debug(parm1.payload);

                    //TODO: 重构到方法里，参照 postDeviceInfoService()
                    //TODO：接收一段时间之内（一天内，一周内的）的环信聊天记录，
                    var entity = new systemChatMessagesEntity();
                    entity.from = parm1.from;
                    entity.to = parm1.to;
                    entity.messageId = parm1.msg_id;
                    entity.chatType = parm1.type;
                    //logger.debug(">>>>>>payload.bodies[0].msg:");
                    //logger.debug(parm1.payload.bodies[0].msg)
                    entity.message = parm1.payload.bodies[0].msg;
                    entity.messageTime = parm1.timestamp;
                    var messageType = parm1.payload.bodies[0].type;
                    entity.messageType = messageType;

                    if (messageType == "img" || messageType == "audio") {
                        entity.url = parm1.payload.bodies[0].url;//TODO:不填充还是写0，
                        entity.filename = parm1.payload.bodies[0].filename;
                        entity.secret = parm1.payload.bodies[0].secret;
                        if (messageType == "audio") {
                            entity.length = parm1.payload.bodies[0].length;
                        }
                    } else if (messageType == "loc") {
                        entity.lat = parm1.payload.bodies[0].lat;
                        entity.lng = parm1.payload.bodies[0].lng;
                        entity.address = parm1.payload.bodies[0].address;
                    }
                    entity.save();
                })

            }).on('error', function (err) {
                logger.error('sendMessageByCustomService' + err.message);
            });


            /*
             TODO: 循环获取记录
             logger.debug(">>>>>>count1:");
             var count1 = 1;//TODO:重命名,默认值为多少，
             var cursor1 = "MTYxOTcyOTYyNDpnR2tBQVFNQWdHa0FCZ0ZHczFuSG93Q0FkUUFROW94S0lQZVBFZU9mTEQxQWVMdHEyQUNBZFFBUTlvd2pFUGVQRWVPaHFWa1l0ZjA2dEFB";
             while (count1 != 0) {//TODO while获取，直到count=0
             sleep(3);//TODO:接口限流说明: 同一个IP每秒最多可调用1次, 超过的部分会返回503错误, 所以在调用程序中, 如果碰到了这样的错误, 需要稍微暂停一下并且重试。
             restClient.get("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/chatmessages?limit=10&ql=select+*+where+timestamp>1425139200000&cursor="+cursor1, args, function (data, response) {//下一页
             logger.debug("1>>>>>>exportChatMessageListService(),（环信导出聊天记录）");
             logger.debug(">>>>>>data:");

             logger.debug(">>>>>>data.cursor:");
             logger.debug(data.cursor);//count: 收到多少条，
             var cursor1=data.cursor;//TODO:重命名

             logger.debug(">>>>>>data.count:");
             logger.debug(data.count);//count: 收到多少条，
             count1 = data.count;
             logger.debug(data);//count: 收到多少条，
             //TODO: cursor分页方式的response里的 duration=6字段：是【cursor持续6秒】的意思吗？
             data.entities.forEach(function (parm1) {
             logger.debug(">>>>>>parm1:");
             logger.debug(parm1);
             logger.debug(">>>>>>parm1.payload:");
             logger.debug(parm1.payload);

             //TODO: 重构到方法里，参照 postDeviceInfoService()
             //TODO：接收一段时间之内（一天内，一周内的）的环信聊天记录，
             var entity = new systemChatMessagesEntity();
             entity.from = parm1.from;
             entity.to = parm1.to;
             entity.messageId = parm1.msg_id;
             entity.chatType = parm1.type;
             //logger.debug(">>>>>>payload.bodies[0].msg:");
             //logger.debug(parm1.payload.bodies[0].msg)
             entity.message = parm1.payload.bodies[0].msg;
             entity.messageTime = parm1.timestamp;
             var messageType = parm1.payload.bodies[0].type;
             entity.messageType = messageType;

             if (messageType == "img" || messageType == "audio") {
             entity.url = parm1.payload.bodies[0].url;//TODO:不填充还是写0，
             entity.filename = parm1.payload.bodies[0].filename;
             entity.secret = parm1.payload.bodies[0].secret;
             if (messageType == "audio") {
             entity.length = parm1.payload.bodies[0].length;
             }
             } else if (messageType == "loc") {
             entity.lat = parm1.payload.bodies[0].lat;
             entity.lng = parm1.payload.bodies[0].lng;
             entity.address = parm1.payload.bodies[0].address;
             }
             entity.save();
             })

             }).on('error', function (err) {
             logger.error('sendMessageByCustomService' + err.message);
             });
             }//end while*/
        });
    });
};

exports.getHotKeywordsService = function (token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            redisClient.zrange(user.community._id, 0, 4, callback);
        }
    });
};

//=========================================== Web后台管理 ============================================
/**
 * systemService.js
 * 获取所有的短信记录
 * author:chenjinzhuan
 */
//mongoose建立的数据文档与自己建立的数据文档是不一样的，mongoose会将所有的大写字母转为小写，并且会在后面加一个s
//如果数据schema不存在，则需要将所要建立的schema按照mongoose的命名规则进行命名，然后添加文档。或者直接使用mongoose添加文档。
exports.getShortMessageListService = function (callback) {
    codeShortMessage.find({}, function (err, results) {
        if (err) {
            return callback(err, null);
        } else if (results == null || results == undefined) {
            return callback('no results', null);
        } else {
            return callback(null, results);
        }
    });
};


/**
 * systemService.js
 * 搜索短信
 * author:chenjinzhuan
 */
exports.searchShortMessageService = function (input, callback) {

    //设置查询条件
    var query1 = {'deviceId': input.deviceId};
    var query2 = {'mobilePhone': input.mobilePhone};
    var query3 = {'verificationCode': input.verificationCode};
    var query4 = {'messageId': input.messageId};
    var query5 = {'errCode': input.errCode};
    var query6 = {'status': input.status};
    var query7 = {dateCreated: {"$gte": new Date(input.dateStart)}};
    var query8 = {dateCreated: {"$lt": new Date(input.dateEnd)}};

    //如果有变量为null或空字符串，则将查询语句设置为null
    if (input.deviceId == null || input.deviceId == '') {
        query1 = null;
    }
    if (input.mobilePhone == null || input.mobilePhone == '') {
        query2 = null;
    }
    if (input.verificationCode == null || input.verificationCode == '') {
        query3 = null;
    }
    if (input.messageId == null || input.messageId == '') {
        query4 = null;
    }
    if (input.errCode == null || input.errCode == '') {
        query5 = null;
    }
    if (input.status == null || input.status == '') {
        query6 = null;
    }
    if (input.dateStart == null || input.dateStart == '') {
        query7 = null;
    }
    if (input.dateEnd == null || input.dateEnd == '') {
        query8 = null;
    }

    //根据条件查找短信
    codeShortMessage.find({$and: [query1, query2, query3, query4, query5, query6, query7, query8]}, function (err, results) {
        if (err) {
            return callback(err, null);
        } else if (results == null || results == undefined) {
            return callback('no results', null);
        } else {
            return callback(null, results);
        }
    });

};

exports.sendMessageByCustomService = function (communityId, msg, callback) {
    Users.find({'community': communityId}, 'huanxinUserName', function (err, results) {
        var newNames = [];
        var oldNames = [];
        var superNames = [];

        async.each(results, function (user, c1) {
            userDevice.findOne({userId: user._id}, 'vCode', function (err, version) {
                if (version != null && version.vCode != null && version.vCode == appVersionCode) {
                    newNames.push(user.huanxinUserName);
                } else if (version != null && version.vCode != null && version.vCode > appVersionCode) {
                    superNames.push(user.huanxinUserName)
                } else {
                    oldNames.push(user.huanxinUserName);
                }
                c1();
            });
        }, function (err) {
            toolUtil.getAndCacheHuanXinToken(function (err, token) {
                Users.findOne({'nickName': '小6客服'}, '_id images huanxinUserName', function (err, result) {
                    var args = {
                        data: {
                            "target_type": "users",
                            "target": oldNames,
                            "msg": {
                                "type": "txt",
                                "msg": msg
                            },
                            "from": result.huanxinUserName,
                            "ext": {           //扩展属性, 由app自己定义.可以没有这个字段，但是如果有，值不能是“ext:null“这种形式，否则出错
                                "nickName": "小6客服",
                                "avatar": result.images[0].imageURL,
                                "objId": result._id
                            }
                        },
                        headers: {
                            "Content-Type": "application/json",
                            "Authorization": "Bearer " + token
                        }
                    };
                    restClient.post("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/messages", args, function (data, response) {
                        logger.debug(data);
                    }).on('error', function (err) {
                        logger.error('sendMessageByCustomService' + err.message);
                    });


                    var args1 = {
                        data: {
                            "target_type": "users",
                            "target": superNames,
                            "msg": {
                                "type": "txt",
                                "msg": msg
                            },
                            "from": 'superservice',
                            "ext": {           //扩展属性, 由app自己定义.可以没有这个字段，但是如果有，值不能是“ext:null“这种形式，否则出错
                                "nickName": "小6客服",
                                "avatar": result.images[0].imageURL,
                                "objId": result._id
                            }
                        },
                        headers: {
                            "Content-Type": "application/json",
                            "Authorization": "Bearer " + token
                        }
                    };
                    restClient.post("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/messages", args1, function (data, response) {
                        logger.debug(data);
                    }).on('error', function (err) {
                        logger.error('sendMessageByCustomService' + err.message);
                    });

                });
                toolUtil.getCustomerServiceByCommunityId(communityId, function (err, result) {
                    var args = {
                        data: {
                            "target_type": "users",
                            "target": newNames,
                            "msg": {
                                "type": "txt",
                                "msg": msg
                            },
                            "from": result.huanxinUserName,
                            "ext": {           //扩展属性, 由app自己定义.可以没有这个字段，但是如果有，值不能是“ext:null“这种形式，否则出错
                                "nickName": "小6客服",
                                "avatar": result.images[0].imageURL,
                                "objId": result._id
                            }
                        },
                        headers: {
                            "Content-Type": "application/json",
                            "Authorization": "Bearer " + token
                        }
                    };
                    restClient.post("https://a1.easemob.com/66xiaoqu/" + huanxinEnv + "/messages", args, function (data, response) {
                        logger.debug(data);
                    }).on('error', function (err) {
                        logger.error('sendMessageByCustomService' + err.message);
                    });
                });
                callback(null, null);
            });
        });
    })
};


/* 环信IM聊天记录list */
exports.getChatMessageListService = function (callback) {//TODO

    /*//systemChatMessageEntity.find({}, function (err, results) {
     logger.info(">>>>>>getChatMessageListService()");
     //systemChatMessageEntity.find({}, function (err, results) {
     systemChatMessageEntity.find({}, function (err, results) {//TODO
     if (err) {
     return callback(err, null);
     } else if (results == null || results == undefined) {
     return callback('no results', null);
     } else {
     return callback(null, results);
     }
     }).limit(10);*/


    /*TODO*/
    var startDate = new Date(moment().add(-20, 'days').format("YYYY/MM/DD"));
    var endDate = new Date(moment().format("YYYY/MM/DD"));
    //var startDate = new Date("2015-04-01");
    //var endDate = new Date("2015-04-12");
    //var date = new Date(moment().add(-3, 'days').format("YYYY/MM/DD HH:mm:ss"));

    logger.info(">>>>>>getChatMessageListService()");
    systemChatMessageEntity.find({
        'messageTime': {
            '$gte': startDate,
            '$lt': endDate
        }
    }).sort('-messageTime').limit(20).exec(callback);

    /*old备份
     systemChatMessageEntity.find({
     =======
     /*systemChatMessageEntity.find({
     >>>>>>> master
     'messageTime': {'$gte': startDate, '$lt': endDate}
     }, function (err, results) {//TODO
     if (err) {
     return callback(err, null);
     } else if (results == null || results == undefined) {
     return callback('no results', null);
     } else {
     logger.info(">>>>>>results.length:");
     logger.info(results.length);
     <<<<<<< HEAD

     //var resultMap = new Map();
     //resultMap.set(0,results.length);
     //resultMap.set(1,results);

     //var resultArray = new Array();
     //resultArray.push(results.length);
     //resultArray.push(results);

     return callback(null, results);
     //return callback(null, resultMap);
     //return callback(null, resultArray);
     }
     }).sort('-messageTime').limit(5);*/

    //var resultMap = new Map();
    //resultMap.set(0,results.length);
    //resultMap.set(1,results);

    //var resultArray = new Array();
    //resultArray.push(results.length);
    //resultArray.push(results);

    //return callback(null, results);
    //return callback(null, resultMap);
    //return callback(null, resultArray);


    /*appStartInfo.find({
     dateCreated: {$gte: date},
     community: communityId,
     userId: {$ne: null}
     }, function (err, results) {
     async.series([
     function (callbackInner) {
     redisClient.del('u:active', callbackInner)
     },
     function (callbackInner) {
     var uList = new Array();
     results.forEach(function (user) {
     uList.push(user._id);
     });
     if (uList.length > 0)
     redisClient.sadd('u:active', uList, callbackInner)
     else
     callbackInner(null, null);
     },
     function (callbackInner) {
     var keys = ['u:active'];
     redisClient.sdiff('u:c:' + communityId, keys, callbackInner)
     }
     ], callback)
     })
     */


}
exports.searchChatMessageListService = function (input, callback) {//TODO

    /* 聊天联系人 */
    var from = input.inputFrom;
    var to = input.inputFrom;

    logger.debug("input.userId:");
    logger.debug(input.userId);
    var chatFriendUserId = input.userId;


    //设置查询条件
    //var query1 = {'from': from};//old 2015-4-13 20:54:24
    //var query2 = {'to': to};//

    var query1 = {'from': from};//
    var query2 = {'to': to};
    //

    //var query111 = {'from':"13774379111","to":chatFriendUserId}//TODO:写死的，修改过来，
    //var query222 = {'from':chatFriendUserId,"to":"13774379111"}

    /* 搜索：环信IM聊天记录list */
    /*exports.searchChatMessageListService = function (input, callback) {//TODO

     */
    /*TODO*/
    /*
     //var startDate = new Date("2015-04-01");
     //var endDate = new Date("2015-04-12");
     //var date = new Date(moment().add(-3, 'days').format("YYYY/MM/DD HH:mm:ss"));

     */
    /*var startDate = {dateCreated: {"$gte": new Date(input.dateStart)}};
     var endDate = {dateCreated: {"$lt": new Date(input.dateEnd)}};*/
    /*
     var startDate = new Date(input.dateStart);
     var endDate = new Date(input.dateEnd);

     logger.info(">>>>>>searchChatMessageListService()");
     systemChatMessageEntity.find({
     'messageTime': {'$gte': startDate, '$lt': endDate}
     }, function (err, results) {//TODO
     if (err) {
     return callback(err, null);
     } else if (results == null || results == undefined) {
     return callback('no results', null);
     } else {
     logger.info(">>>>>>results.length:");
     logger.info(results.length);

     //var resultMap = new Map();
     //resultMap.set(0,results.length);
     //resultMap.set(1,results);

     var resultArray = new Array();
     resultArray.push(results.length);
     resultArray.push(results);

     return callback(null, results);
     //return callback(null, resultMap);
     //return callback(null, resultArray);
     }
     }).limit(10);

     };*/

    var query3 = {'verificationCode': input.verificationCode};
    var query4 = {'messageType': input.messageType};//
    var query5 = {'errCode': input.errCode};

    /*模糊查询，正则表达式*/
    //var query6 = {'message': /msg.*/};//
    //var query6 = {'message': "/" + msg + ".*/"};//
    //var query6 = {'message': new RegExp('^'+ '123' +'$', "i")};//
    //var query6 = {'message': new RegExp('123', 'i')};//
    var query6 = {'message': new RegExp("123", "i")};//
    //var query6 = {'message': '123132'};//
    //var query6 = {'message': new RegExp('^/.*'+ '123' +'.*/i$')};//

    //var q = new RegExp("^" + "123" +".*");
    //var q = new RegExp('^' + '123' + '.*');
    //var query6 = {'message': {'$all':[q]} };//

    var query7 = {messageTime: {"$gte": new Date(input.dateStart)}};//
    var query8 = {messageTime: {"$lt": new Date(input.dateEnd)}};//

    //如果有变量为null或空字符串，则将查询语句设置为null
    if (from == null || from == '') {//input.from
        query1 = null;
    }
    //if (input.to == null || input.to == '') {
    //    query2 = null;
    //}
    if (to == null || to == '') {//input.from
        query2 = null;
    }

    if (input.verificationCode == null || input.verificationCode == '') {
        query3 = null;
    }
    if (input.messageType == null || input.messageType == '') {
        query4 = null;
    }
    if (input.errCode == null || input.errCode == '') {
        query5 = null;
    }
    if (input.message == null || input.message == '') {
        query6 = null;
    }
    if (input.dateStart == null || input.dateStart == '') {
        query7 = null;
    }
    if (input.dateEnd == null || input.dateEnd == '') {
        query8 = null;
    }

    /* 根据条件查找聊天记录 */
    /*old备份 2015-4-12
     systemChatMessageEntity.find({$and: [query1, query2, query3, query4, query5, query6, query7, query8]}, function (err, results) {
     if (err) {
     return callback(err, null);
     } else if (results == null || results == undefined) {
     return callback('no results', null);
     } else {
     return callback(null, results);
     }
     });*/

    /* new 2015-4-13*/
    //systemChatMessageEntity.find({ "$or":[query1,query2], $and:[query7,query8] }).sort('-messageTime').limit(50).exec(callback);//old 2015-4-13 20:54:35
    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).sort('-messageTime').limit(50).exec(callback);

    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).sort('-messageTime').limit(50).exec(callback);//new 2015-4-13 22:24:10


    /*distinct*/
    //var arr = new Array();
    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).distinct("to").exec(callback);//newnew 2015-4-13 22:24:54
    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).distinct("to").exec(callback);

    //systemChatMessageEntity.find({'from':"13774379111"}).distinct("to").exec(callback);
    //systemChatMessageEntity.find({'to':"13774379111"}).distinct("from").exec(callback);

    /* TODO */
    /*systemChatMessageEntity.find({'from':"13774379111"}).distinct("to",function(err,results){
     var array1 = new Array();
     var array2 = new Array();
     array1 = results;

     logger.debug("arr:");
     }).exec(callback);*/

    /*systemChatMessageEntity.find({'from':"13774379111"}).distinct("to").exec(function(err,results){
     var array1 = new Array();
     var array2 = new Array();
     array1 = results;

     logger.debug("arr:");
     systemChatMessageEntity.find({'to':"13774379111"}).distinct("from").exec(function(err,results){
     array2 = results;
     });
     logger.debug("arr:");
     callback(err, result);
     });*/


    async.series([
        function (callbackInner) {
            /*appStartInfo.count({
             dateCreated: {
             $gte: opt.startTime,
             $lt: opt.endTime
             }
             }, callbackInner)*/
            systemChatMessageEntity.find(query1).distinct("to", callbackInner)//TODO，写死了，
        },
        function (callbackInner) {
            systemChatMessageEntity.find(query2).distinct("from", callbackInner)

            /*appStartInfo.find({
             dateCreated: {
             $gte: opt.startTime,
             $lt: opt.endTime
             }
             }).distinct('userId', function (err, results) {
             callbackInner(err, results == null ? 0 : results.length);
             })*/
        }
    ], callback)

    /*specialTopics.findOne({
     _id: id
     }, 'title desc dateCreated comments.commentDesc comments.commentedBy comments.commentedDate')
     .populate('comments.commentedBy', '_id nickName images').exec(function (err, result) {
     if (result != null) {
     var date = moment(result.dateCreated).format('YYYY-MM-DD HH:mm');
     var header = '<B><font  size="5">' + result.title + '</font></B><br>' + date + '<br>'
     result.desc = header + result.desc;
     }
     callback(err, result);
     });*/

    /*appStartInfo.find({
     dateCreated: {
     $gte: opt.startTime,
     $lt: opt.endTime
     }
     }).distinct('userId', function (err, results) {
     callbackInner(err, results == null ? 0 : results.length);
     })*/

    //systemChatMessageEntity.find({ "$or":[{'from':"13774379111"}, {'to':"13774379111"}] }).distinct("from").exec(callback);//漏掉记录
    //systemChatMessageEntity.find({ "$or":[{'from':"13774379111"}, {'to':"13774379111"}] }).distinct("from,to").exec(callback);//行不通

    //logger.debug("arr:");
    //logger.debug(arr);

};


/**
 * 搜索某人和他的一位朋友的聊天记录
 * @param input 入参
 * @param callback
 */
exports.searchChatLogByTwoUserService = function (input, callback) {//TODO
    logger.debug(">>>>>>searchChatLogByTwoUserService()");

    /* 聊天联系人 */
    var from = input.someoneUserId;//某人
    var chatFriendUserId = input.friendUserId;//某人的一位朋友
    //var chatFriendUserId =  input.userId;

    logger.debug("input.someoneUserId:");
    logger.debug(from);
    logger.debug("input.friendUserId:");
    logger.debug(chatFriendUserId);


    //设置查询条件
    var query111 = {'from': from, "to": chatFriendUserId}//TODO:写死的，修改过来，
    var query222 = {'from': chatFriendUserId, "to": from}


    //var query1 = {'from': from};//old 2015-4-13 20:54:24
    //var query2 = {'to': to};//

    var query1 = {'from': from};//
    var query2 = {'to': '13774379621'};//


    var query3 = {'verificationCode': input.verificationCode};
    var query4 = {'messageType': input.messageType};//
    var query5 = {'errCode': input.errCode};

    /*模糊查询，正则表达式*/
    //var query6 = {'message': /msg.*/};//
    //var query6 = {'message': "/" + msg + ".*/"};//
    //var query6 = {'message': new RegExp('^'+ '123' +'$', "i")};//
    //var query6 = {'message': new RegExp('123', 'i')};//
    var query6 = {'message': new RegExp("123", "i")};//
    //var query6 = {'message': '123132'};//
    //var query6 = {'message': new RegExp('^/.*'+ '123' +'.*/i$')};//

    //var q = new RegExp("^" + "123" +".*");
    //var q = new RegExp('^' + '123' + '.*');
    //var query6 = {'message': {'$all':[q]} };//


    var query7 = {messageTime: {"$gte": new Date(input.dateStart)}};//
    var query8 = {messageTime: {"$lt": new Date(input.dateEnd)}};//

    //如果有变量为null或空字符串，则将查询语句设置为null
    if (from == null || from == '') {//input.from
        query1 = null;
    }
    //if (input.to == null || input.to == '') {
    //    query2 = null;
    //}

    //if (to == null || to == '') {//input.from
    //    query2 = null;
    //}

    if (input.verificationCode == null || input.verificationCode == '') {
        query3 = null;
    }
    if (input.messageType == null || input.messageType == '') {
        query4 = null;
    }
    if (input.errCode == null || input.errCode == '') {
        query5 = null;
    }
    if (input.message == null || input.message == '') {
        query6 = null;
    }
    if (input.dateStart == null || input.dateStart == '') {
        query7 = null;
    }
    if (input.dateEnd == null || input.dateEnd == '') {
        query8 = null;
    }

    /* 根据条件查找聊天记录 */
    /*old备份 2015-4-12
     systemChatMessageEntity.find({$and: [query1, query2, query3, query4, query5, query6, query7, query8]}, function (err, results) {
     if (err) {
     return callback(err, null);
     } else if (results == null || results == undefined) {
     return callback('no results', null);
     } else {
     return callback(null, results);
     }
     });*/


    //TODO: 查询某人和他朋友的聊天记录，2015-04-14
    /* new 2015-4-13*/
    //systemChatMessageEntity.find({ "$or":[query1,query2], $and:[query7,query8] }).sort('-messageTime').limit(50).exec(callback);//old 2015-4-13 20:54:35
    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).sort('-messageTime').limit(50).exec(callback);

    systemChatMessageEntity.find({
        "$or": [query111, query222],
        $and: [query7, query8]
    }).sort('-messageTime').limit(100).exec(callback);//new 2015-4-13 22:24:10//TODO：分页（每页多少条记录）


    /*distinct*/
    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).distinct("to").exec(callback);//newnew 2015-4-13 22:24:54
    //systemChatMessageEntity.find({ "$or":[query111,query222], $and:[query7,query8] }).distinct("to").exec(callback);


    /* ?? */
    //systemChatMessageEntity.find({'from':"13774379111"}).distinct("to").exec(callback);
    //systemChatMessageEntity.find({'to':"13774379111"}).distinct("from").exec(callback);


    /* TODO */
    /*systemChatMessageEntity.find({'from':"13774379111"}).distinct("to",function(err,results){
     var array1 = new Array();
     var array2 = new Array();
     array1 = results;

     logger.debug("arr:");
     }).exec(callback);*/

    /*systemChatMessageEntity.find({'from':"13774379111"}).distinct("to").exec(function(err,results){
     var array1 = new Array();
     var array2 = new Array();
     array1 = results;

     logger.debug("arr:");
     systemChatMessageEntity.find({'to':"13774379111"}).distinct("from").exec(function(err,results){
     array2 = results;
     });
     logger.debug("arr:");
     callback(err, result);
     });*/


    /*specialTopics.findOne({
     _id: id
     }, 'title desc dateCreated comments.commentDesc comments.commentedBy comments.commentedDate')
     .populate('comments.commentedBy', '_id nickName images').exec(function (err, result) {
     if (result != null) {
     var date = moment(result.dateCreated).format('YYYY-MM-DD HH:mm');
     var header = '<B><font  size="5">' + result.title + '</font></B><br>' + date + '<br>'
     result.desc = header + result.desc;
     }
     callback(err, result);
     });*/

    /*appStartInfo.find({
     dateCreated: {
     $gte: opt.startTime,
     $lt: opt.endTime
     }
     }).distinct('userId', function (err, results) {
     callbackInner(err, results == null ? 0 : results.length);
     })*/

    //systemChatMessageEntity.find({ "$or":[{'from':"13774379111"}, {'to':"13774379111"}] }).distinct("from").exec(callback);//漏掉记录
    //systemChatMessageEntity.find({ "$or":[{'from':"13774379111"}, {'to':"13774379111"}] }).distinct("from,to").exec(callback);//行不通

    logger.debug(">>>>>>end searchChatLogByTwoUserService()");

};


/**
 * 获取专题详情
 */
exports.getDetailOfSpecialTopicService = function (token, id, callback) {

    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            specialTopics.findOne({
                _id: id
            }, 'title desc dateCreated comments.commentDesc comments.commentedBy comments.commentedDate')
                .populate('comments.commentedBy', '_id nickName images community').exec(function (err, result) {
                    var uList = []
                    if (result != null) {
                        var date = moment(result.dateCreated).format('YYYY-MM-DD HH:mm');
                        var header = '<B><font  size="5">' + result.title + '</font></B><br>' + date + '<br>'
                        result.desc = header + result.desc;
                        if (result.comments != null) {
                            result.comments.forEach(function (comment) {
                                if (comment.commentedBy.community == user.community._id) {
                                    uList.push(comment)
                                }
                            })
                        }
                    }
                    uList.forEach(function (user) {
                        user.commentedBy.community = undefined;
                    });
                    result.comments = uList;
                    callback(err, result);
                });
        }
    });
};

exports.getTopicReplyService = function (page, id, token, vcode, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            specialTopics.findOne({
                _id: id
            }, 'title dateCreated comments')
                .populate('comments.commentedBy', '_id nickName images community').exec(function (err, result) {
                    var uList = [];
                    if (result != null && result.comments != null) {
                        async.each(result.comments, function (comment, callback1) {
                            if (comment.commentedBy.community == user.community._id) {

                                if (comment.commentDesc != null && comment.commentDesc.indexOf(atFlag) != -1) {

                                    replyAt.findOne({replyId: comment._id + ''}, function (err, at) {
                                        if (at != null && at.uList != null) {
                                            if (vcode < 1500) {
                                                at.uList.forEach(function (temp, i) {
                                                    comment.commentDesc = comment.commentDesc.replace(new RegExp("@\\{" + i + "\\}"), '@' + temp.nickName + ' ')
                                                });
                                            } else {
                                                comment._doc['uList'] = at.uList;
                                            }
                                        }
                                        uList.push(comment);
                                        callback1(err, null);
                                    }).populate('uList', '_id nickName');
                                } else {
                                    uList.push(comment);
                                    callback1()
                                }
                            } else {
                                callback1();
                            }
                        }, function (err) {
                            uList.forEach(function (user) {
                                user.commentedBy.community = undefined;
                            });

                            page = Number(page);
                            var replies = uList.slice(page * listPageSize, (page + 1) * listPageSize);

                            result.comments = replies;
                            callback(err, result);
                        })
                    } else {
                        callback(err, result);
                    }
                });
        }
    })
};

exports.getSpecialTopicListService = function (page, token, callback) {
    var index = Number(page) * 10;

    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            specialTopics.find({
                community: user.community._id,
                isValid: true
            }, '_id title imageURL dateCreated dateLastModified').sort('-dateCreated').skip(index).limit(10)
                .exec(function (err, result) {
                    if (result != null) {
                        result.forEach(function (topic) {
                            topic._doc['url'] = TopicsHost + '/' + topic._id + '.html'
                        });
                    }
                    callback(err, result);
                });
        }
    });
};

exports.postSpecialTopicCommentService = function (input, token, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null);
        } else {
            var temp = {
                "commentDesc": input.commentDesc,
                "commentedBy": user._id
            };
            async.series([
                function (callbackInner) {
                    specialTopics.update({_id: input.topicId}, {$push: {'comments': temp}}).exec(callbackInner);
                },
                function (callbackInner) {
                    specialTopics.findOne({_id: input.topicId}, callbackInner)
                }
            ], callback)
        }
    });
};

exports.postSpecialTopicService = function (input, callback) {

    if (input.id == null) {
        var temp = new specialTopics();
        temp.title = input.title;
        temp.imageURL = input.imageURL;
        temp.desc = input.desc;
        temp.community = input.community;
        temp.summary = input.summary;
        temp.save(callback);
        exports.generateTopicHtml(temp, topicPath)
    } else {
        specialTopics.update({_id: input.id}, {
            title: input.title,
            imageURL: input.imageURL,
            desc: input.desc,
            community: input.community,
            summary: input.summary,
            dateLastModified: new Date()
        }, callback);
        exports.generateTopicHtml(input, topicPath)
    }
};

//var fullpath="../static/mobile/topic";
var fullpath = resTopicPath();
exports.generateTopicHtml = function (specialTopicsObj, path) {
    //fs.mkdir("../static",0777,function(err){})
    //fs.mkdir("../static/mobile",0777,function(err){})
    //fs.mkdir(fullpath,0777,function(err){})
    var str = fs.readFileSync("public/pages/static/mobile/js/topic/template.html", 'utf-8');
    var array = str.split('{{}}');
    var id = specialTopicsObj._id ? specialTopicsObj._id : specialTopicsObj.id;
    var date = moment().format('YYYY-MM-DD HH:mm');
    if (specialTopicsObj.dateCreated != null) {
        date = moment(specialTopicsObj.dateCreated).format('YYYY-MM-DD HH:mm');
    }
    var header = '<B><font  size="5">' + specialTopicsObj.title + '</font></B><br>' + date + '<br>';

    fs.writeFile(path + "/" + id + ".html", array[0] + header + specialTopicsObj.desc + array[1], function (err) {
    });
};

exports.getAllTopic = function (callback) {
    specialTopics.find(callback);
}

exports.remove = function (id) {
    fs.unlink(fullpath + "/" + id + ".html", function (err) {
        console.log(err)
    });
}

exports.createSpecialNewsService = function (input, callback) {
    var temp = new freshNews();
    temp.openType = 5;
    temp.tag = input.type;
    temp.title = input.title;
    temp.community = input.community;
    temp.url = input.url;
    temp.save(callback);
};

exports.removeNewsService = function (newsId, callback) {
    freshNews.remove({_id: newsId}, callback);
};

exports.getSpecialNewsListService = function (communityId, callback) {
    if (communityId == '1') {
        freshNews.find({}, 'url tag title dateCreated community').sort('-displayOrder').populate('community', 'communityName')
            .sort('-dateCreated').exec(callback);
    } else {
        freshNews.find({community: communityId}, 'url tag title dateCreated community').sort('-displayOrder').populate('community', 'communityName')
            .sort('-dateCreated').exec(callback);
    }
};

exports.confirmOrderService = function (input, callback) {
    var a = input.length;
    async.eachSeries(input, function (newsId, callbackInner) {
        freshNews.update({_id: newsId}, {displayOrder: a}, function (err, result) {
            a--;
            callbackInner(err, result);
        })
    }, function (err) {
        callback(err, null);
    })
};

exports.getPushUserListService = function (input, callback) {
    var opt = {
        community: input.communityId
    }
    logger.debug(opt);

    async.series([

        function (callbacIknner) {
            Users.find(opt, '_id', function (err, result) {
                var data = new Array();
                result.forEach(function (user) {
                    data.push(user._id);
                });
                callbacIknner(err, data);
            })

        },
        function (callbacIknner) {

            var body = {
                 user_id : input.userId
                ,action : 'push'
                ,action_id : input.contentId
            };
            logger.debug(body);
            var sql = "insert into 66xiaoqu_log.user_action_log set ?";
            mysqlUtil.queryBI(sql, [body], function (err, result) {
                callbacIknner(err, result);
            });

        }
    ], callback);



};

exports.getAllCommunityTopicService = function (communityId, status, callback) {

    var opt = {};
    if (status == '1') {
        opt.isValid = true;
    }
    if (communityId != '1') {
        opt.community = communityId;
    }
    specialTopics.find(opt).populate('community', '_id communityName').sort('-dateCreated').exec(function (err, result) {
        if (result != null) {
            result.forEach(function (topic) {
                topic._doc['url'] = TopicsHost + '/' + topic._id + '.html'
            });
        }
        callback(err, result);
    });
};


exports.setTopicStatusService = function (input, callback) {
    specialTopics.update({_id: input.id}, {isValid: input.status}, callback);
};

exports.getTopicByIdService = function (id, callback) {
    specialTopics.findOne({_id: id}).populate('community', '_id communityName').exec(function (err, result) {
        callback(err, result);
    });
};

exports.updateTopicService = function (input, callback) {

};

exports.getCommunityActivityListService = function (communityId, callback) {
    SystemBanner.findOne({community: communityId, isValid: true}, 'banner', function (err, result) {
        var data = [];
        if (result != null && result.banner != null) {
            result.banner.forEach(function (banner) {
                var temp = {
                    _id: banner.activityId,
                    title: banner.title,
                    url: banner.desc
                };
                data.push(temp);
            })
        }
        callback(null, data);
    })
};

/**
 * 取得环信聊天记录--环信支持app把聊天记录通过REST接口导出
 */
exports.getEasemobChatLogListService = function (communityId, callback) {
    SystemBanner.findOne({community: communityId, isValid: true}, 'banner', function (err, result) {
        var data = [];
        if (result != null && result.banner != null) {
            result.banner.forEach(function (banner) {
                var temp = {
                    _id: banner.activityId,
                    title: banner.title,
                    url: banner.desc
                };
                data.push(temp);
            })
        }
        callback(null, data);
    })
};


exports.getAllCommunityStatisticsService = function (callback) {

    var start = new Date(moment().add(-1, 'days').format("YYYY/MM/DD"));
    var end = new Date(moment().format("YYYY/MM/DD"));

    async.series([
        function (callbackInner) {
            var time = new Date(new Date().getTime() - 10 * 60 * 1000);
            Question.count({
                '$or': [ {replies:{$exists: false}},{replies:{$size: 0}} ] ,
                isValid: true,
                fromFlag:{$ne:'service'},
                category:'question',
                dateCreated: {$lt: time}
            }, callbackInner)
        },
        function (callbackInner) {
            QuestionReport.count({'$or':[{reportStatus:0},{reportStatus:{$exists: false}}]}, callbackInner);
        },
        function (callbackInner) {
            userAuthentication.count({
                status: false,
                isValid: true
            }, callbackInner);
        },
        function (callbackInner) {
            system_userFeedbacks.count({dateCreated: {$gte: end}}, callbackInner);
        },
        function (callbackInner) {
            communitySupplement.count({dateCreated: {$gte: end}}, callbackInner);
        },
        function (callbackInner) {
            Users.count({
                dateCreated: {
                    $gte: start,
                    $lt: end
                }
            }, callbackInner);
        },
        function (callbackInner) {
            Question.count({
                dateCreated: {
                    $gte: start,
                    $lt: end
                }
            }, callbackInner);
        },
        function (callbackInner) {
            Question.find({
                'replies.dateReplied': {
                    $gte: start,
                    $lt: end
                }
            }, 'replies').exec(function (err, results) {
                var count = 0;
                results.forEach(function (question) {
                    question.replies.forEach(function (reply) {
                        if (reply.dateReplied > start && reply.dateReplied < end) {
                            count++;
                        }
                    })
                });
                callbackInner(err, count);
            });
        },
        function (callbackInner) {
            replyAtService.count({
                status: true
            }, callbackInner);
        }

    ], callback)
};

exports.getNotActiveUserService = function (communityId, callback) {
    var date = new Date(moment().add(-3, 'days').format("YYYY/MM/DD HH:mm:ss"));
    appStartInfo.find({
        dateCreated: {$gte: date},
        community: communityId,
        userId: {$ne: null}
    }, function (err, results) {
        async.series([
            function (callbackInner) {
                redisClient.del('u:active', callbackInner)
            },
            function (callbackInner) {
                var uList = new Array();
                results.forEach(function (user) {
                    uList.push(user._id);
                });
                if (uList.length > 0)
                    redisClient.sadd('u:active', uList, callbackInner)
                else
                    callbackInner(null, null);
            },
            function (callbackInner) {
                var keys = ['u:active'];
                redisClient.sdiff('u:c:' + communityId, keys, callbackInner)
            }
        ], callback)
    })
};


exports.acceptSmsRtService = function (input, callback) {
    codeShortMessage.update({messageId: input.messageId}, {status: input.status, errCode: input.errCode}, callback)
};

exports.deleteTopicService = function (id, callback) {
    async.series([
        function (callbackInner) {
            specialTopics.remove({_id: id}, callbackInner)
            exports.remove(id);
        },
        function (callbackInner) {
            operateMessage.remove({messageId: id}, callbackInner);
        }
    ], callback)
};

exports.shortUrlService = function (url, callback) {
    restClient.get("http://api.t.sina.com.cn/short_url/shorten.json?source=1908276038&url_long=" + url, function (data, response) {
        if (response.statusCode == 200) {
            if (typeof data == 'string') {
                data = JSON.parse(data)
            }
            var shortUrl = data[0].url_short;
            callback(null, shortUrl)
        } else {
            callback(null, url);
        }
    }).on('error', function (err) {
        callback(null, url);
    });
};

exports.generatePromotionCodeService = function (input, callback) {
    var length = input.number;
    var expirationDate = new Date(input.expirationDate);
    expirationDate.setHours(expirationDate.getHours() - 8)

    var date = new Date();

    toolUtil.getPromotionCode(length, function (err, codes) {
        async.each(codes, function (code, callbackInner) {
            var temp = new promotionCode();
            temp.code = code;
            temp.dateCreated = date;
            temp.expirationDate = expirationDate;
            temp.save(callbackInner);
        }, function (err) {
            callback(null, null);
        })
    });
};

exports.getPromotionCodeListService = function (input, callback) {
    promotionCode.find(input).sort('-dateCreated').exec(callback);
};

exports.getPromotionCodeDateCreatedService = function (callback) {
    async.series([
        function (callbackInner) {
            promotionCode.distinct('dateCreated').exec(callbackInner);
        },
        function (callbackInner) {
            promotionCode.distinct('expirationDate').exec(callbackInner);
        }
    ], callback)
};

exports.setPromotionCodeOwnerService = function (input, callback) {
    promotionCode.update({_id: input._id}, {owner: input.owner}, callback)
};

exports.receiveOfflineMessageService = function (input, callback) {
    async.series([
        function (callbackInner) {
            var temp = new offlineMessage();
            temp.callId = input.callId;
            temp.eventType = input.eventType;
            temp.timestamp = input.timestamp;
            temp.from = input.from;
            temp.to = input.to;
            temp.save(callbackInner);
        },
        function (callbackInner) {
            Users.findOne({huanxinUserName: input.to}, function (err, user) {
                var content = {
                    type: 2,
                    flag: 4,
                    openType: 7,
                    contentId: input.from,
                    desc: '你有一条新消息'
                };
                var pushData = {
                    uList: [user._id],
                    content: content,
                    type: 'chat'
                };
                //toolUtil.putMessageGetuiPushMQ(pushData);
                callbackInner(err, null);
            });
        }
    ], callback)
};

exports.setOfflineMessageAsReadService = function (token, huanxinId, callback) {
    toolUtil.getUserByToken(token, function (err, user) {
        if (err) {
            callback(err, null)
        } else {
            offlineMessage.update({to: user.huanxinUserName}, {readFlag: true}, {multi: true}).exec(callbackInner)
        }
    })
};
exports.appErrorLogService = function (errorLog, callback) {
    var objErrorLog = new appErrorLog();
    objErrorLog.userId = errorLog.userId;
    objErrorLog.deviceId = errorLog.deviceId;
    objErrorLog.osType = errorLog.osType;
    objErrorLog.osModel = errorLog.osModel;
    objErrorLog.appvName = errorLog.appvName;
    objErrorLog.sysvName = errorLog.sysvName;
    objErrorLog.errorMsg = errorLog.errorMsg;
    objErrorLog.errorCode = errorLog.errorCode;
    objErrorLog.url = errorLog.url;
    objErrorLog.save(callback);
};
exports.getAppErrorLogListService = function (input, callback) {
    appErrorLog.find(input).sort('-dateCreated').exec(callback);
};

//获取需求推送消息、话题、Banner的人数
exports.getPushGroupListService = function (opt, callback) {

    var queryUserIn = {};
    queryUserIn["$in"] = opt;

    var option ={};
    option["community"] = queryUserIn;

    logger.debug(option);
    Users.find(option, '_id', function (err, result) {
        //var data = new Array();
        var data ={};
        //result.forEach(function (user) {
        //    data.push(user._id);
        //});
        data['ucount'] = result.length;
        logger.debug(data);
        callback(err, data);
    })
};


exports.confirmGroupPushService = function (req, callback) {

    var input = req.body.questionList;

    async.eachSeries(input, function (item, callbackInner) {

        var opt = {};
        var aroundCommunity = [];

        if(item.aroundCommunity != null && item.aroundCommunity != []){
            aroundCommunity.push(item.community);
            item.aroundCommunity.forEach(function(ac){
                aroundCommunity.push(ac._id);
            });
            opt['community'] = {'$in': aroundCommunity};
        }else{
            opt['community'] = item.community;
        };

        Users.find(opt, '_id', function (err, result) {
            var content = {
                type: 1,
                flag: 2,
                openType: req.body.openType,
                contentId: item.contentId,
                createdBy: item.createdBy,
                desc: req.body.desc
            };
            var data = new Array();

            result.forEach(function (user) {
                data.push(user._id);
            });
            var pushData = {
                uList: data,
                content: content,
                ip: req.headers['X-Real-IP'],
                tag: req.body.tag,
                type: 'operate'
            };
            toolUtil.putMessageGetuiPushMQ(pushData);

            callbackInner();
        });
    }, function (err) {
        callback(err, req);
    });


};

exports.getTopicByFilterService = function (option, callback){

    if (option['title'] != null) {
        option['title'] = new RegExp(option['title']);
    }

    specialTopics.find(option)
        .sort('-dateCreated')
        .populate('community', 'communityName')
        .exec(function (err, result) {
            if (result != null && result.length > 0) {
                result.forEach(function (topic) {
                    topic._doc['url'] = TopicsHost + '/' + topic._id + '.html'
                });
            }
            callback(null, result);
        });
};

exports.getTopicByFilterPagingService = function (pageSize, pageNumber,opt, callback) {

    if(opt.title){
        opt.title =  new RegExp(opt['title']);
    };
    for (var item in opt) {
        if (opt[item] == null) {
            delete opt[item];
        }
    };

    //var opt = {};
    //if (status == '1') {
    //    opt.isValid = true;
    //}
    //if (communityId != '1') {
    //    opt.community = communityId;
    //};
    logger.debug(pageSize);
    logger.debug(pageNumber);

    async.series([
        function (callbacIknner) {
            specialTopics.count(opt, function (err, count) {
                callbacIknner(err, Math.ceil(count / pageSize));
            });
        },
        function (callbackInner) {
            var index = (Number(pageNumber) - 1) * pageSize;
            logger.debug(index);
            specialTopics.find(opt).populate('community', '_id communityName').sort('-dateCreated')
                .skip(index).limit(listPageSize).exec(function (err, result) {
                if (result != null) {
                    result.forEach(function (topic) {
                        topic._doc['url'] = TopicsHost + '/' + topic._id + '.html'
                    });
                };
                callbackInner(err, result);
            });
        }
    ], callback);

};